#include "SpecialProj.h"
#include "Emitter.h"
#include "DestroyEntityMessage.h"
#include "MessageSystem.h"
#include "SGD Wrappers/CSGD_Direct3D.h"
#include "Particle.h"
#include "EventSystem.h"
#include "Enemy.h"
#include "Tile.h"
#include "Player.h"
//#include "GamePlayState.h"

SpecialProj::SpecialProj(BulletType bType)
{
	bulletType = bType;
	type = OBJ_BULLET;

	switch(bType)
	{
	case EMP_BURST:
		{
			sfx = Emitter::LoadEmitter("emitters/EMPBurst.xml");
			lifeSpan = 1;
			damageRate = 0.25f;
			moveDistance = 0;
		}
		break;

	case NAPALM:
		{
			sfx = Emitter::LoadEmitter("emitters/fire.xml");
			lifeSpan = 5;
			damageRate = 0.25f;
			moveDistance = 0.5;
		}
		break;
	}
	lifeTimer = 0;
	damageTimer = 0;
	moveTimer = 0;
	collisionReady = true;
}

SpecialProj::~SpecialProj(void)
{
	sfx->Loop(false);
	sfx->Shutdown();
	delete sfx;
}

void SpecialProj::Update(float elapsed)
{
	lifeTimer += elapsed;
	damageTimer += elapsed;
	moveTimer += elapsed;

	if(lifeTimer >= lifeSpan)
	{
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;
	}

	if(damageTimer >= damageRate)
	{
		collisionReady = true;
	}

	if(moveTimer < moveDistance)
	{
		switch(GetDirection())
		{
			//Up
		case 3:
			SetY(GetY() - GetMoveSpeed() * elapsed);
			break;
			//Right
		case 0:
			SetX(GetX() + GetMoveSpeed() * elapsed);
			break;
			//Down
		case 2:
			SetY(GetY() + GetMoveSpeed() * elapsed);
			break;
			//Left
		case 1:
			SetX(GetX() - GetMoveSpeed() * elapsed);
			break;
		}
	}
	
	sfx->SetPosition(GetX(), GetY());
	sfx->Update(elapsed);
}

void SpecialProj::Render()
{
	CSGD_Direct3D::GetInstance()->GetSprite()->Flush();

	sfx->Render();

	/*float camX = GamePlayState::GetInstance()->GetCamX();
	float camY = GamePlayState::GetInstance()->GetCamY();

	RECT tmp;
	tmp.left = GetRect().left - camX;
	tmp.right = GetRect().right - camX;
	tmp.top = GetRect().top - camY;
	tmp.bottom = GetRect().bottom - camY;

	CSGD_Direct3D::GetInstance()->DrawRect(tmp , 0, 255, 255);*/
}

bool SpecialProj::CheckCollision(IEntity* base)
{
	if(collisionReady == false)
		return false;

	if(Entity::CheckCollision(base) == true && base != this->GetOwner())
	{
		if((GetOwnerType() == OBJ_PLAYER && base->GetType() == OBJ_ENEMY))
		{
			EventSystem::GetInstance()->SendEvent("target_hit", base, new float(GetDamage()));
			collisionReady = false;
			damageTimer = 0;

			if(GetBulletType() == EMP_BURST)
				dynamic_cast<Enemy*>(base)->SetStunTime(3.0f);
			else if(this->GetBulletType() == NAPALM)
				dynamic_cast<Enemy*>(base)->SetSlow(1.0f, 0.5f);
		}

		if(GetOwnerType() == OBJ_ENEMY && base->GetType() == OBJ_PLAYER)
		{
			EventSystem::GetInstance()->SendEvent("player_hit", base, new float(GetDamage()),
			new int(dynamic_cast<Player*>(base)->GetPlayerNum()));
			collisionReady = false;
			damageTimer = 0;
		}

		if(base->GetType() == OBJ_TILE)
		{
			if(dynamic_cast<Tile*>(base)->GetTileType() != TILE_COLLISION)
				return false;
			else
			{
				if(GetBulletType() == NAPALM)
				{
					moveTimer = moveDistance;
				}
			}
		}

		if(base->GetType() == OBJ_BULLET || base->GetType() == OBJ_WEAPON || base->GetType() == OBJ_PICKUP ||
			base->GetType() == GetOwnerType())
			return false;

		/*else
		{
			DestroyEntityMessage* msg = new DestroyEntityMessage(this);
			MessageSystem::GetInstance()->SendMsg(msg);
			msg = nullptr;
		}*/

		return true;
	}

	return false;
}

RECT SpecialProj::GetRect()
{
	RECT tmp = {};

	switch(bulletType)
	{
	case EMP_BURST:
		{
			switch(GetDirection())
			{
				//Up
			case 3:
				tmp.top    = (long)GetY() - 100;
				tmp.bottom = (long)GetY();
				tmp.left   = (long)GetX() - 50;
				tmp.right  = (long)GetX() + 50;
				break;
				//Right
			case 0:
				tmp.top		= (long)GetY() - 50;
				tmp.bottom	= (long)GetY() + 50;
				tmp.left	= (long)GetX();
				tmp.right	= (long)GetX() + 100;
				break;
				//Down
			case 2:
				tmp.top		= (long)GetY();
				tmp.bottom	= (long)GetY() + 100;
				tmp.left	= (long)GetX() - 50;
				tmp.right	= (long)GetX() + 50;
				break;
				//Left
			case 1:
				tmp.top		= (long)GetY() - 50;
				tmp.bottom	= (long)GetY() + 50;
				tmp.left	= (long)GetX() - 100;
				tmp.right	= (long)GetX();
				break;
			}
		}
		break;

	case NAPALM:
		{
			tmp = Projectile::GetRect();
		}
		break;
	}

	

	return tmp;
}

void SpecialProj::SetDirection(int d)
{
	int width = GetOwner()->GetWidth();
	int height = GetOwner()->GetHeight();
	int x = (int)GetOwner()->GetX();
	int y = (int)GetOwner()->GetY();

	Projectile::SetDirection(d);

	float dir = 0.0f;

	// Modified to fix bug where EMP shot in the wrong direction
	switch(d)
	{
		//Up
	case 1:
		dir = SGD_PI/2;
		SetPosition(x, y);
		break;
		//Right
	case 2:
		dir = 0;
		SetPosition(x + width, y + height);
		break;
		//Down
	case 0:
		dir = (3*SGD_PI)/2;
		SetPosition(x, y + height);
		break;
		//Left
	case 3:
		dir = (SGD_PI);
		SetPosition(x - width, y + height);
		break;
	}

	sfx->SetPosition(GetX(), GetY());

	sfx->GetMaster()->SetRotation(dir);

	sfx->Loop();
}
